package com.heima.behavior.service.impl;

import com.heima.behavior.doc.ApFollowBehavior;
import com.heima.behavior.service.ApFollowBehaviorService;
import com.heima.common.exception.LogicException;
import com.heima.common.exception.ParamException;
import com.heima.model.behavior.dto.FollowBehaviorDto;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.common.util.UserInfoThreadLocal;
import com.heima.common.util.LoginUserInfo;
import com.heima.model.common.enums.BehaviorRedisKeyEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;

@Service
@Slf4j
public class ApFollowBehaviorServiceImpl implements ApFollowBehaviorService {

    @Resource
    private MongoTemplate mongoTemplate;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public void follow(FollowBehaviorDto dto) {
        // 1. 检查参数
        if (dto.getAuthorId() == null) {
            throw new ParamException(AppHttpCodeEnum.PARAM_REQUIRE);
        }

        // 2. 获取当前用户
        LoginUserInfo userInfo = UserInfoThreadLocal.get();
        if (userInfo == null) {
            throw new LogicException(AppHttpCodeEnum.NEED_LOGIN);
        }

        // 3. 不能关注自己
        if (userInfo.getId().equals(dto.getAuthorId().longValue())) {
            throw new LogicException(AppHttpCodeEnum.PARAM_INVALID);
        }

        // 4. 构建关注行为对象
        ApFollowBehavior followBehavior = ApFollowBehavior.builder()
                .userId(userInfo.getId())
                .followId(dto.getAuthorId())
                .articleId(dto.getArticleId())
                .createdTime(new Date())
                .build();
        // 5. 根据操作类型执行关注或取消关注
        if (dto.getOperation() == 0) {
            // 关注操作
            // 查询是否已经关注过
            Query query = Query.query(Criteria.where("userId").is(userInfo.getId().intValue())
                    .and("followId").is(dto.getAuthorId()));

            ApFollowBehavior one = mongoTemplate.findOne(query, ApFollowBehavior.class);
            if (one == null) {
                // 没有关注记录，新增关注
                mongoTemplate.save(followBehavior);
            }
        } else {
            // 取消关注操作
            Query query = Query.query(Criteria.where("userId").is(userInfo.getId().intValue())
                    .and("followId").is(dto.getAuthorId()));

            mongoTemplate.remove(query, ApFollowBehavior.class);
        }

        // 6. 更新Redis缓存
        String followKey = BehaviorRedisKeyEnum.FOLLOW_BEHAVIOR_PREFIX.buildKey(userInfo.getId());
        String fansKey = BehaviorRedisKeyEnum.FANS_PREFIX.buildKey(dto.getAuthorId());

        if (dto.getOperation() == 0) {
            // 关注操作，添加到Redis set中
            stringRedisTemplate.opsForSet().add(followKey, String.valueOf(dto.getAuthorId()));
            stringRedisTemplate.opsForSet().add(fansKey, String.valueOf(userInfo.getId()));
        } else {
            // 取消关注操作，从Redis set中移除
            stringRedisTemplate.opsForSet().remove(followKey, String.valueOf(dto.getAuthorId()));
            stringRedisTemplate.opsForSet().remove(fansKey, String.valueOf(userInfo.getId()));
        }

    }
}
